home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / compiler / life.lisp < prev    next >
Encoding:
Text File  |  1992-12-09  |  39.0 KB  |  1,133 lines

  1. ;;; -*- Package: C; Log: C.Log -*-
  2. ;;;
  3. ;;; **********************************************************************
  4. ;;; This code was written as part of the CMU Common Lisp project at
  5. ;;; Carnegie Mellon University, and has been placed in the public domain.
  6. ;;; If you want to use this code or any part of CMU Common Lisp, please contact
  7. ;;; Scott Fahlman or slisp-group@cs.cmu.edu.
  8. ;;;
  9. (ext:file-comment
  10.   "$Header: life.lisp,v 1.21 92/08/14 15:20:19 ram Exp $")
  11. ;;;
  12. ;;; **********************************************************************
  13. ;;;
  14. ;;;    This file contains the lifetime analysis phase in the compiler.
  15. ;;;
  16. ;;; Written by Rob MacLachlan
  17. ;;;
  18. (in-package 'c)
  19.  
  20.  
  21. ;;;; Utilities:
  22.  
  23. ;;; Add-Global-Conflict  --  Internal
  24. ;;;
  25. ;;;    Link in a global-conflicts structure for TN in Block with Number as the
  26. ;;; LTN number.  The conflict is inserted in the per-TN Global-Conflicts thread
  27. ;;; after the TN's Current-Conflict.  We change the Current-Conflict to point
  28. ;;; to the new conflict.  Since we scan the blocks in reverse DFO, this list is
  29. ;;; automatically built in order.  We have to actually scan the current
  30. ;;; Global-TNs for the block in order to keep that thread sorted.
  31. ;;;
  32. (defun add-global-conflict (kind tn block number)
  33.   (declare (type (member :read :write :read-only :live) kind)
  34.        (type tn tn) (type ir2-block block)
  35.        (type (or local-tn-number null) number))
  36.   (let ((new (make-global-conflicts kind tn block number)))
  37.     (let ((last (tn-current-conflict tn)))
  38.       (if last
  39.       (shiftf (global-conflicts-tn-next new)
  40.           (global-conflicts-tn-next last)
  41.           new)
  42.       (shiftf (global-conflicts-tn-next new)
  43.           (tn-global-conflicts tn)
  44.           new)))
  45.     (setf (tn-current-conflict tn) new)
  46.  
  47.     (insert-block-global-conflict new block))
  48.   (undefined-value))
  49.  
  50.  
  51. ;;; INSERT-BLOCK-GLOBAL-CONFLICT  --  Internal
  52. ;;;
  53. ;;;    Do the actual insertion of the conflict New into Block's global
  54. ;;; conflicts.
  55. ;;; 
  56. (defun insert-block-global-conflict (new block)
  57.   (let ((global-num (tn-number (global-conflicts-tn new))))
  58.     (do ((prev nil conf)
  59.      (conf (ir2-block-global-tns block)
  60.            (global-conflicts-next conf)))
  61.     ((or (null conf)
  62.          (> (tn-number (global-conflicts-tn conf)) global-num))
  63.      (if prev
  64.          (setf (global-conflicts-next prev) new)
  65.          (setf (ir2-block-global-tns block) new))
  66.      (setf (global-conflicts-next new) conf))))
  67.   (undefined-value))
  68.  
  69.  
  70. ;;; Reset-Current-Conflict  --  Internal
  71. ;;;
  72. ;;;    Reset the Current-Conflict slot in all packed TNs to point to the head
  73. ;;; of the Global-Conflicts thread.
  74. ;;;
  75. (defun reset-current-conflict (component)
  76.   (do-packed-tns (tn component)
  77.     (setf (tn-current-conflict tn) (tn-global-conflicts tn))))
  78.  
  79.  
  80. ;;;; Pre-pass:
  81.  
  82. ;;; Convert-To-Global  --  Internal
  83. ;;;
  84. ;;;    Convert TN (currently local) to be a global TN, since we discovered that
  85. ;;; it is referenced in more than one block.  We just add a global-conflicts
  86. ;;; structure with a kind derived from the Kill and Live sets.
  87. ;;;
  88. (defun convert-to-global (tn)
  89.   (declare (type tn tn))
  90.   (let ((block (tn-local tn))
  91.     (num (tn-local-number tn)))
  92.     (add-global-conflict
  93.      (if (zerop (sbit (ir2-block-written block) num))
  94.      :read-only
  95.      (if (zerop (sbit (ir2-block-live-out block) num))
  96.          :write
  97.          :read))
  98.      tn block num))
  99.   (undefined-value))
  100.  
  101.  
  102. ;;; Find-Local-References  --  Internal
  103. ;;;
  104. ;;;    Scan all references to packed TNs in block.  We assign LTN numbers to
  105. ;;; each referenced TN, and also build the Kill and Live sets that summarize
  106. ;;; the references to each TN for purposes of lifetime analysis.
  107. ;;;
  108. ;;;    It is possible that we will run out of LTN numbers.  If this happens,
  109. ;;; then we return the VOP that we were processing at the time we ran out,
  110. ;;; otherwise we return NIL.
  111. ;;;
  112. ;;;    If a TN is referenced in more than one block, then we must represent
  113. ;;; references using Global-Conflicts structures.  When we first see a TN, we
  114. ;;; assume it will be local.  If we see a reference later on in a different
  115. ;;; block, then we go back and fix the TN to global.
  116. ;;;
  117. ;;;    We must globalize TNs that have a block other than the current one in
  118. ;;; their Local slot and have no Global-Conflicts.  The latter condition is
  119. ;;; necessary because we always set Local and Local-Number when we process a
  120. ;;; reference to a TN, even when the TN is already known to be global.
  121. ;;;
  122. ;;;    When we see reference to global TNs during the scan, we add the
  123. ;;; global-conflict as :Read-Only, since we don't know the corrent kind until
  124. ;;; we are done scanning the block.
  125. ;;;
  126. (defun find-local-references (block)
  127.   (declare (type ir2-block block))
  128.   (let ((kill (ir2-block-written block))
  129.     (live (ir2-block-live-out block))
  130.     (tns (ir2-block-local-tns block)))
  131.     (let ((ltn-num (ir2-block-local-tn-count block)))
  132.       (do ((vop (ir2-block-last-vop block)
  133.         (vop-prev vop)))
  134.       ((null vop))
  135.     (do ((ref (vop-refs vop) (tn-ref-next-ref ref)))
  136.         ((null ref))
  137.       (let* ((tn (tn-ref-tn ref))
  138.          (local (tn-local tn))
  139.          (kind (tn-kind tn)))
  140.         (unless (member kind '(:component :environment :constant))
  141.           (unless (eq local block)
  142.         (when (= ltn-num local-tn-limit)
  143.           (return-from find-local-references vop))
  144.         (when local
  145.           (unless (tn-global-conflicts tn)
  146.             (convert-to-global tn))
  147.           (add-global-conflict :read-only tn block ltn-num))
  148.         
  149.         (setf (tn-local tn) block)
  150.         (setf (tn-local-number tn) ltn-num)
  151.         (setf (svref tns ltn-num) tn)
  152.         (incf ltn-num))
  153.           
  154.           (let ((num (tn-local-number tn)))
  155.         (if (tn-ref-write-p ref)
  156.             (setf (sbit kill num) 1  (sbit live num) 0)
  157.             (setf (sbit live num) 1)))))))
  158.       
  159.       (setf (ir2-block-local-tn-count block) ltn-num)))
  160.   nil)
  161.  
  162.  
  163. ;;; Init-Global-Conflict-Kind   --  Internal
  164. ;;;
  165. ;;;    Finish up the global conflicts for TNs referenced in Block according to
  166. ;;; the local Kill and Live sets.
  167. ;;;
  168. ;;;    We set the kind for TNs already in the global-TNs.  If not written at
  169. ;;; all, then is :Read-Only, the default.  Must have been referenced somehow,
  170. ;;; or we wouldn't have conflicts for it.
  171. ;;;
  172. ;;;    We also iterate over all the local TNs, looking for TNs local to this
  173. ;;; block that are still live at the block beginning, and thus must be global.
  174. ;;; This case is only important when a TN is read in a block but not written in
  175. ;;; any other, since otherwise the write would promote the TN to global.  But
  176. ;;; this does happen with various passing-location TNs that are magically
  177. ;;; written.  This also serves to propagate the lives of erroneously
  178. ;;; uninitialized TNs so that consistency checks can detect them.
  179. ;;;
  180. (defun init-global-conflict-kind (block)
  181.   (declare (type ir2-block block))
  182.   (let ((live (ir2-block-live-out block)))
  183.     (let ((kill (ir2-block-written block)))
  184.       (do ((conf (ir2-block-global-tns block)
  185.          (global-conflicts-next conf)))
  186.       ((null conf))
  187.     (let ((num (global-conflicts-number conf)))
  188.       (unless (zerop (sbit kill num))
  189.         (setf (global-conflicts-kind conf)
  190.           (if (zerop (sbit live num))
  191.               :write
  192.               :read))))))
  193.     
  194.     (let ((ltns (ir2-block-local-tns block)))
  195.       (dotimes (i (ir2-block-local-tn-count block))
  196.     (let ((tn (svref ltns i)))
  197.       (unless (or (eq tn :more)
  198.               (tn-global-conflicts tn)
  199.               (zerop (sbit live i)))
  200.         (convert-to-global tn))))))
  201.   
  202.   (undefined-value))
  203.  
  204.  
  205. (defevent split-ir2-block "Split an IR2 block to meet Local-TN-Limit.")
  206.  
  207. ;;; Split-IR2-Blocks  --  Internal
  208. ;;;
  209. ;;;    Move the code after the VOP Lose in 2block into its own block.  The
  210. ;;; block is linked into the emit order following 2block.  Number is the block
  211. ;;; number assigned to the new block.  We return the new block.
  212. ;;;
  213. (defun split-ir2-blocks (2block lose number)
  214.   (declare (type ir2-block 2block) (type vop lose)
  215.        (type unsigned-byte number))
  216.   (event split-ir2-block (vop-node lose))
  217.   (let ((new (make-ir2-block (ir2-block-block 2block)))
  218.     (new-start (vop-next lose)))
  219.     (setf (ir2-block-number new) number)
  220.     (add-to-emit-order new 2block)
  221.  
  222.     (do ((vop new-start (vop-next vop)))
  223.     ((null vop))
  224.       (setf (vop-block vop) new))
  225.     
  226.     (setf (ir2-block-start-vop new) new-start)
  227.     (shiftf (ir2-block-last-vop new) (ir2-block-last-vop 2block) lose)
  228.  
  229.     (setf (vop-next lose) nil)
  230.     (setf (vop-prev new-start) nil)
  231.  
  232.     new))
  233.  
  234.  
  235. ;;; Clear-Lifetime-Info  --  Internal
  236. ;;;
  237. ;;;    Clear the global and local conflict info in Block so that we can
  238. ;;; recompute it without any old cruft being retained.  It is assumed that all
  239. ;;; LTN numbers are in use.
  240. ;;;
  241. ;;;    First we delete all the global conflicts.  The conflict we are deleting
  242. ;;; must be the last in the TN's global-conflicts, but we must scan for it in
  243. ;;; order to find the previous conflict.
  244. ;;;
  245. ;;;    Next, we scan the local TNs, nulling out the Local slot in all TNs with
  246. ;;; no global conflicts.  This allows these TNs to be treated as local when we
  247. ;;; scan the block again.
  248. ;;;
  249. ;;;    If there are conflicts, then we set Local to one of the conflicting
  250. ;;; blocks.  This ensures that Local doesn't hold over Block as its value,
  251. ;;; causing the subsequent reanalysis to think that the TN has already been
  252. ;;; seen in that block.
  253. ;;;
  254. ;;;    This function must not be called on blocks that have :More TNs.
  255. ;;;
  256. (defun clear-lifetime-info (block)
  257.   (declare (type ir2-block block))
  258.   (setf (ir2-block-local-tn-count block) 0)
  259.   
  260.   (do ((conf (ir2-block-global-tns block)
  261.          (global-conflicts-next conf)))
  262.       ((null conf)
  263.        (setf (ir2-block-global-tns block) nil))
  264.     (let ((tn (global-conflicts-tn conf)))
  265.       (assert (eq (tn-current-conflict tn) conf))
  266.       (assert (null (global-conflicts-tn-next conf)))
  267.       (do ((current (tn-global-conflicts tn)
  268.             (global-conflicts-tn-next current))
  269.        (prev nil current))
  270.       ((eq current conf)
  271.        (if prev
  272.            (setf (global-conflicts-tn-next prev) nil)
  273.            (setf (tn-global-conflicts tn) nil))
  274.        (setf (tn-current-conflict tn) prev)))))
  275.   
  276.   (fill (ir2-block-written block) 0)
  277.   (let ((ltns (ir2-block-local-tns block)))
  278.     (dotimes (i local-tn-limit)
  279.       (let ((tn (svref ltns i)))
  280.     (assert (not (eq tn :more)))
  281.     (let ((conf (tn-global-conflicts tn)))
  282.       (setf (tn-local tn)
  283.         (if conf
  284.             (global-conflicts-block conf)
  285.             nil))))))
  286.   
  287.   (undefined-value))
  288.  
  289.  
  290. ;;; Coalesce-More-LTN-Numbers  --  Internal
  291. ;;;
  292. ;;;    This provides a panic mode for assigning LTN numbers when there is a VOP
  293. ;;; with so many more operands that they can't all be assigned distinct
  294. ;;; numbers.  When this happens, we recover by assigning all the more operands
  295. ;;; the same LTN number.  We can get away with this, since all more args (and
  296. ;;; results) are referenced simultaneously as far as conflict analysis is
  297. ;;; concerned.
  298. ;;;
  299. ;;;     Block is the IR2-Block that the more VOP is at the end of.  Ops is the
  300. ;;; full argument or result TN-Ref list.  Fixed is the types of the fixed
  301. ;;; operands (used only to skip those operands.)
  302. ;;;
  303. ;;;     What we do is grab a LTN number, then make a :Read-Only global conflict
  304. ;;; for each more operand TN.  We require that there be no existing global
  305. ;;; conflict in Block for any of the operands.  Since conflicts must be cleared
  306. ;;; before the first call, this only prohibits the same TN being used both as a
  307. ;;; more operand and as any other operand to the same VOP.
  308. ;;;
  309. ;;;     We don't have to worry about getting the correct conflict kind, since
  310. ;;; Init-Global-Conflict-Kind will fix things up.  Similarly,
  311. ;;; FIND-LOCAL-REFERENCES will set the local conflict bit corresponding to this
  312. ;;; call.
  313. ;;;
  314. ;;;     We also set the Local and Local-Number slots in each TN.  It is
  315. ;;; possible that there are no operands in any given call to this function, but
  316. ;;; there had better be either some more args or more results.
  317. ;;;
  318. (defun coalesce-more-ltn-numbers (block ops fixed)
  319.   (declare (type ir2-block block) (type (or tn-ref null) ops) (list fixed))
  320.   (let ((num (ir2-block-local-tn-count block)))
  321.     (assert (< num local-tn-limit))
  322.     (incf (ir2-block-local-tn-count block))
  323.     (setf (svref (ir2-block-local-tns block) num) :more)
  324.  
  325.     (do ((op (do ((op ops (tn-ref-across op))
  326.           (i 0 (1+ i)))
  327.          ((= i (length fixed)) op)
  328.            (declare (type index i)))
  329.          (tn-ref-across op)))
  330.     ((null op))
  331.       (let ((tn (tn-ref-tn op)))
  332.     (assert
  333.       (flet ((frob (refs)
  334.            (do ((ref refs (tn-ref-next ref)))
  335.                ((null ref) t)
  336.              (when (and (eq (vop-block (tn-ref-vop ref)) block)
  337.                 (not (eq ref op)))
  338.                (return nil)))))
  339.         (and (frob (tn-reads tn)) (frob (tn-writes tn))))
  340.       () "More operand ~S used more than once in its VOP." op)
  341.     (assert (not (find-in #'global-conflicts-next tn
  342.                   (ir2-block-global-tns block)
  343.                   :key #'global-conflicts-tn)))
  344.  
  345.     (add-global-conflict :read-only tn block num)
  346.     (setf (tn-local tn) block)
  347.     (setf (tn-local-number tn) num))))
  348.   (undefined-value))
  349.  
  350.  
  351. (defevent coalesce-more-ltn-numbers
  352.   "Coalesced LTN numbers for a more operand to meet Local-TN-Limit.")
  353.  
  354. ;;; Lifetime-Pre-Pass  --  Internal
  355. ;;;
  356. ;;;    Loop over the blocks in Component, assigning LTN numbers and recording
  357. ;;; TN birth and death.  The only interesting action is when we run out of
  358. ;;; local TN numbers while finding local references.
  359. ;;;
  360. ;;;    If we run out of LTN numbers while processing a VOP within the block,
  361. ;;; then we just split off the VOPs we have successfully processed into their
  362. ;;; own block.
  363. ;;;
  364. ;;;    If we run out of LTN numbers while processing the our first VOP (the
  365. ;;; last in the block), then it must be the case that this VOP has large more
  366. ;;; operands.  We split the VOP into its own block, and then call
  367. ;;; Coalesce-More-Ltn-Numbers to assign all the more args/results the same LTN
  368. ;;; number(s).
  369. ;;;
  370. ;;;    In either case, we clear the lifetime information that we computed so
  371. ;;; far, recomputing it after taking corrective action.
  372. ;;;
  373. ;;;    Whenever we split a block, we finish the pre-pass on the split-off block
  374. ;;; by doing Find-Local-References and Init-Global-Conflict-Kind.  This can't
  375. ;;; run out of LTN numbers.
  376. ;;;
  377. (defun lifetime-pre-pass (component)
  378.   (declare (type component component))
  379.   (let ((counter -1))
  380.     (declare (type fixnum counter))
  381.     (do-blocks-backwards (block component)
  382.       (let ((2block (block-info block)))
  383.     (do ((lose (find-local-references 2block)
  384.            (find-local-references 2block))
  385.          (last-lose nil lose)
  386.          (coalesced nil))
  387.         ((not lose)
  388.          (init-global-conflict-kind 2block)
  389.          (setf (ir2-block-number 2block) (incf counter)))
  390.       
  391.       (clear-lifetime-info 2block)
  392.       
  393.       (cond
  394.        ((vop-next lose)
  395.         (assert (not (eq last-lose lose)))
  396.         (let ((new (split-ir2-blocks 2block lose (incf counter))))
  397.           (assert (not (find-local-references new)))
  398.           (init-global-conflict-kind new)))
  399.        (t
  400.         (assert (not (eq lose coalesced)))
  401.         (setq coalesced lose)
  402.         (event coalesce-more-ltn-numbers (vop-node lose))
  403.         (let ((info (vop-info lose))
  404.           (new (if (vop-prev lose)
  405.                (split-ir2-blocks 2block (vop-prev lose)
  406.                          (incf counter))
  407.                2block)))
  408.           (coalesce-more-ltn-numbers new (vop-args lose)
  409.                      (vop-info-arg-types info))
  410.           (coalesce-more-ltn-numbers new (vop-results lose)
  411.                      (vop-info-result-types info))
  412.           (let ((lose (find-local-references new)))
  413.         (assert (not lose)))
  414.           (init-global-conflict-kind new))))))))
  415.              
  416.   (undefined-value))
  417.  
  418.  
  419. ;;;; Environment TN stuff:
  420.  
  421.  
  422. ;;; SETUP-ENVIRONMENT-TN-CONFLICT  --  Internal
  423. ;;;
  424. ;;;    Add a :LIVE global conflict for TN in 2block if there is none present.
  425. ;;; If Debug-P is false (a :ENVIRONMENT TN), then modify any existing conflict
  426. ;;; to be :LIVE.
  427. ;;;
  428. (defun setup-environment-tn-conflict (tn 2block debug-p)
  429.   (declare (type tn tn) (type ir2-block 2block))
  430.   (let ((block-num (ir2-block-number 2block)))
  431.     (do ((conf (tn-current-conflict tn) (global-conflicts-tn-next conf))
  432.      (prev nil conf))
  433.     ((or (null conf)
  434.          (> (ir2-block-number (global-conflicts-block conf)) block-num))
  435.      (setf (tn-current-conflict tn) prev)
  436.      (add-global-conflict :live tn 2block nil))
  437.       (when (eq (global-conflicts-block conf) 2block)
  438.     (unless (or debug-p
  439.             (eq (global-conflicts-kind conf) :live))
  440.       (setf (global-conflicts-kind conf) :live)
  441.       (setf (svref (ir2-block-local-tns 2block)
  442.                (global-conflicts-number conf))
  443.         nil)
  444.       (setf (global-conflicts-number conf) nil))
  445.     (setf (tn-current-conflict tn) conf)
  446.     (return))))
  447.   (undefined-value))
  448.  
  449.  
  450. ;;; SETUP-ENVIRONMENT-TN-CONFLICTS  --  Internal
  451. ;;;
  452. ;;;    Iterate over all the blocks in Env, setting up :LIVE conflicts for TN.
  453. ;;; We make the TN global if it isn't already.  The TN must have at least one
  454. ;;; reference.
  455. ;;;
  456. (defun setup-environment-tn-conflicts (component tn env debug-p)
  457.   (declare (type component component) (type tn tn) (type environment env))
  458.   (when (and debug-p
  459.          (not (tn-global-conflicts tn))
  460.          (tn-local tn))
  461.     (convert-to-global tn))
  462.   (setf (tn-current-conflict tn) (tn-global-conflicts tn))
  463.   (do-blocks-backwards (block component)
  464.     (when (eq (block-environment block) env)
  465.       (let* ((2block (block-info block))
  466.          (last (do ((b (ir2-block-next 2block) (ir2-block-next b))
  467.             (prev 2block b))
  468.                ((not (eq (ir2-block-block b) block))
  469.             prev))))
  470.     (do ((b last (ir2-block-prev b)))
  471.         ((not (eq (ir2-block-block b) block)))
  472.       (setup-environment-tn-conflict tn b debug-p)))))
  473.   (undefined-value))
  474.  
  475.   
  476. ;;; SETUP-ENVIRONMENT-LIVE-CONFLICTS  --  Internal
  477. ;;;
  478. ;;;    Iterate over all the environment TNs, adding always-live conflicts as
  479. ;;; appropriate.
  480. ;;;
  481. (defun setup-environment-live-conflicts (component)
  482.   (declare (type component component))
  483.   (dolist (fun (component-lambdas component))
  484.     (let* ((env (lambda-environment fun))
  485.        (2env (environment-info env)))
  486.       (dolist (tn (ir2-environment-live-tns 2env))
  487.     (setup-environment-tn-conflicts component tn env nil))
  488.       (dolist (tn (ir2-environment-debug-live-tns 2env))
  489.     (setup-environment-tn-conflicts component tn env t))))
  490.   (undefined-value))
  491.  
  492.  
  493. ;;; Convert-To-Environment-TN  --  Internal
  494. ;;;
  495. ;;;    Convert a :NORMAL or :DEBUG-ENVIRONMENT TN to an :ENVIRONMENT TN.  This
  496. ;;; requires adding :LIVE conflicts to all blocks in TN-ENV.
  497. ;;;
  498. (defun convert-to-environment-tn (tn tn-env)
  499.   (declare (type tn tn) (type environment tn-env))
  500.   (assert (member (tn-kind tn) '(:normal :debug-environment)))
  501.   (when (eq (tn-kind tn) :debug-environment)
  502.     (assert (eq (tn-environment tn) tn-env))
  503.     (let ((2env (environment-info tn-env)))
  504.       (setf (ir2-environment-debug-live-tns 2env)
  505.         (delete tn (ir2-environment-debug-live-tns 2env)))))
  506.   (setup-environment-tn-conflicts *compile-component* tn tn-env nil)
  507.   (setf (tn-local tn) nil)
  508.   (setf (tn-local-number tn) nil)
  509.   (setf (tn-kind tn) :environment)
  510.   (setf (tn-environment tn) tn-env)
  511.   (push tn (ir2-environment-live-tns (environment-info tn-env)))
  512.   (undefined-value))
  513.  
  514.  
  515. ;;;; Flow analysis:
  516.  
  517. ;;; Propagate-Live-TNs  --  Internal
  518. ;;;
  519. ;;;    For each Global-TN in Block2 that is :Live, :Read or :Read-Only, ensure
  520. ;;; that there is a corresponding Global-Conflict in Block1.  If there is none,
  521. ;;; make a :Live Global-Conflict.  If there is a :Read-Only conflict, promote
  522. ;;; it to :Live.
  523. ;;;
  524. ;;;    If we did added a new conflict, return true, otherwise false.  We don't
  525. ;;; need to return true when we promote a :Read-Only conflict, since it doesn't
  526. ;;; reveal any new information to predecessors of Block1.
  527. ;;;
  528. ;;;    We use the Tn-Current-Conflict to walk through the global
  529. ;;; conflicts.  Since the global conflicts for a TN are ordered by block, we
  530. ;;; can be sure that the Current-Conflict always points at or before the block
  531. ;;; that we are looking at.  This allows us to quickly determine if there is a
  532. ;;; global conflict for a given TN in Block1.
  533. ;;;
  534. ;;;    When we scan down the conflicts, we know that there must be at least one
  535. ;;; conflict for TN, since we got our hands on TN by picking it out of a
  536. ;;; conflict in Block2.
  537. ;;;
  538. ;;;    We leave the Current-Conflict pointing to the conflict for Block1.  The
  539. ;;; Current-Conflict must be initialized to the head of the Global-Conflicts
  540. ;;; for the TN between each flow analysis iteration.
  541. ;;;
  542. (defun propagate-live-tns (block1 block2)
  543.   (declare (type ir2-block block1 block2))
  544.   (let ((live-in (ir2-block-live-in block1))
  545.     (did-something nil))
  546.     (do ((conf2 (ir2-block-global-tns block2)
  547.         (global-conflicts-next conf2)))
  548.     ((null conf2))
  549.       (ecase (global-conflicts-kind conf2)
  550.     ((:live :read :read-only)
  551.      (let* ((tn (global-conflicts-tn conf2))
  552.         (tn-conflicts (tn-current-conflict tn))
  553.         (number1 (ir2-block-number block1)))
  554.        (assert tn-conflicts)
  555.        (do ((current tn-conflicts (global-conflicts-tn-next current))
  556.         (prev nil current))
  557.            ((or (null current)
  558.             (> (ir2-block-number (global-conflicts-block current))
  559.                number1))
  560.         (setf (tn-current-conflict tn) prev)
  561.         (add-global-conflict :live tn block1 nil)
  562.         (setq did-something t))
  563.          (when (eq (global-conflicts-block current) block1)
  564.            (case (global-conflicts-kind current)
  565.          (:live)
  566.          (:read-only
  567.           (setf (global-conflicts-kind current) :live)
  568.           (setf (svref (ir2-block-local-tns block1)
  569.                    (global-conflicts-number current))
  570.             nil)
  571.           (setf (global-conflicts-number current) nil)
  572.           (setf (tn-current-conflict tn) current))
  573.          (t
  574.           (setf (sbit live-in (global-conflicts-number current)) 1)))
  575.            (return)))))
  576.     (:write)))
  577.     did-something))
  578.  
  579.             
  580. ;;; Lifetime-Flow-Analysis  --  Internal
  581. ;;;
  582. ;;;    Do backward global flow analysis to find all TNs live at each block
  583. ;;; boundary.
  584. ;;;
  585. (defun lifetime-flow-analysis (component)
  586.   (loop
  587.     (reset-current-conflict component)
  588.     (let ((did-something nil))
  589.       (do-blocks-backwards (block component)
  590.     (let* ((2block (block-info block))
  591.            (last (do ((b (ir2-block-next 2block) (ir2-block-next b))
  592.               (prev 2block b))
  593.              ((not (eq (ir2-block-block b) block))
  594.               prev))))
  595.  
  596.       (dolist (b (block-succ block))
  597.         (when (and (block-start b)
  598.                (propagate-live-tns last (block-info b)))
  599.           (setq did-something t)))
  600.  
  601.       (do ((b (ir2-block-prev last) (ir2-block-prev b))
  602.            (prev last b))
  603.           ((not (eq (ir2-block-block b) block)))
  604.         (when (propagate-live-tns b prev)
  605.           (setq did-something t)))))
  606.  
  607.       (unless did-something (return))))
  608.  
  609.   (undefined-value))
  610.  
  611.  
  612. ;;;; Post-pass:
  613.  
  614. ;;; Note-Conflicts  --  Internal
  615. ;;;
  616. ;;;    Note that TN conflicts with all current live TNs.  Num is TN's LTN
  617. ;;; number.  We bit-ior Live-Bits with TN's Local-Conflicts, and set TN's
  618. ;;; number in the conflicts of all TNs in Live-List.
  619. ;;;
  620. (defun note-conflicts (live-bits live-list tn num)
  621.   (declare (type tn tn) (type (or tn null) live-list)
  622.        (type local-tn-bit-vector live-bits)
  623.        (type local-tn-number num))
  624.   (let ((lconf (tn-local-conflicts tn)))
  625.     (bit-ior live-bits lconf lconf))
  626.   (do ((live live-list (tn-next* live)))
  627.       ((null live))
  628.     (setf (sbit (tn-local-conflicts live) num) 1))
  629.   (undefined-value))
  630.  
  631.  
  632. ;;; Compute-Save-Set  --  Internal
  633. ;;;
  634. ;;;    Compute a bit vector of the TNs live after VOP that aren't results.
  635. ;;;
  636. (defun compute-save-set (vop live-bits)
  637.   (declare (type vop vop) (type local-tn-bit-vector live-bits))
  638.   (let ((live (bit-vector-copy live-bits)))
  639.     (do ((r (vop-results vop) (tn-ref-across r)))
  640.     ((null r))
  641.       (let ((tn (tn-ref-tn r)))
  642.     (ecase (tn-kind tn)
  643.       ((:normal :debug-environment)
  644.        (setf (sbit live (tn-local-number tn)) 0))
  645.       (:environment :component))))
  646.     live))
  647.  
  648.  
  649. ;;; SAVED-AFTER-READ  --  Internal
  650. ;;;
  651. ;;;    Used to determine whether a :DEBUG-ENVIRONMENT TN should be considered
  652. ;;; live at block end.  We return true if a VOP with non-null SAVE-P appears
  653. ;;; before the first read of TN (hence is seen first in our backward scan.)
  654. ;;; 
  655. (defun saved-after-read (tn block)
  656.   (do ((vop (ir2-block-last-vop block) (vop-prev vop)))
  657.       ((null vop) t)
  658.     (when (vop-info-save-p (vop-info vop)) (return t))
  659.     (when (find-in #'tn-ref-across tn (vop-args vop) :key #'tn-ref-tn)
  660.       (return nil))))
  661.  
  662. ;;; MAKE-DEBUG-ENVIRONMENT-TNS-LIVE  --  Internal
  663. ;;;
  664. ;;; If the block has no successors, or its successor is the component tail,
  665. ;;; then all :DEBUG-ENVIRONMENT TNs are always added, regardless of whether
  666. ;;; they appeared to be live.  This ensures that these TNs are considered to be
  667. ;;; live throughout blocks that read them, but don't have any interesting
  668. ;;; successors (such as a return or tail call.)  In this case, we set the
  669. ;;; corresponding bit in LIVE-IN as well.
  670. ;;;
  671. (defun make-debug-environment-tns-live (block live-bits live-list)
  672.   (let* ((1block (ir2-block-block block))
  673.      (live-in (ir2-block-live-in block))
  674.      (succ (block-succ 1block))
  675.      (next (ir2-block-next block)))
  676.     (when (and next
  677.            (not (eq (ir2-block-block next) 1block))
  678.            (or (null succ)
  679.            (eq (first succ)
  680.                (component-tail (block-component 1block)))))
  681.       (do ((conf (ir2-block-global-tns block)
  682.          (global-conflicts-next conf)))
  683.       ((null conf))
  684.     (let* ((tn (global-conflicts-tn conf))
  685.            (num (global-conflicts-number conf)))
  686.       (when (and num (zerop (sbit live-bits num))
  687.              (eq (tn-kind tn) :debug-environment)
  688.              (eq (tn-environment tn) (block-environment 1block))
  689.              (saved-after-read tn block))
  690.         (note-conflicts live-bits live-list tn num)
  691.         (setf (sbit live-bits num) 1)
  692.         (push-in tn-next* tn live-list)
  693.         (setf (sbit live-in num) 1))))))
  694.   
  695.   (values live-bits live-list))
  696.  
  697.  
  698. ;;; Compute-Initial-Conflicts  --  Internal
  699. ;;;
  700. ;;;    Return as values, a LTN bit-vector and a list (threaded by TN-Next*)
  701. ;;; representing the TNs live at the end of Block (exclusive of :Live TNs).
  702. ;;;
  703. ;;; We iterate over the TNs in the global conflicts that are live at the block
  704. ;;; end, setting up the TN-Local-Conflicts and TN-Local-Number, and adding the
  705. ;;; TN to the live list.
  706. ;;;
  707. ;;; If a :MORE result is not live, we effectively fake a read to it.  This is
  708. ;;; part of the action described in ENSURE-RESULTS-LIVE.
  709. ;;;
  710. ;;; At the end, we call MAKE-DEBUG-ENVIRONEMNT-TNS-LIVE to make debug
  711. ;;; environment TNs appear live when appropriate, even when they aren't.
  712. ;;;
  713. ;;; ### Note: we alias the global-conflicts-conflicts here as the
  714. ;;; tn-local-conflicts.
  715. ;;;
  716. (defun compute-initial-conflicts (block)
  717.   (declare (type ir2-block block))
  718.   (let* ((live-in (ir2-block-live-in block))
  719.      (ltns (ir2-block-local-tns block))
  720.      (live-bits (bit-vector-copy live-in))
  721.      (live-list nil))
  722.  
  723.     (do ((conf (ir2-block-global-tns block)
  724.            (global-conflicts-next conf)))
  725.     ((null conf))
  726.       (let ((bits (global-conflicts-conflicts conf))
  727.         (tn (global-conflicts-tn conf))
  728.         (num (global-conflicts-number conf))
  729.         (kind (global-conflicts-kind conf)))
  730.     (setf (tn-local-number tn) num)
  731.     (unless (eq kind :live)
  732.       (cond ((not (zerop (sbit live-bits num)))
  733.          (bit-vector-replace bits live-bits)
  734.          (setf (sbit bits num) 0)
  735.          (push-in tn-next* tn live-list))
  736.         ((and (eq (svref ltns num) :more)
  737.               (eq kind :write))
  738.          (note-conflicts live-bits live-list tn num)
  739.          (setf (sbit live-bits num) 1)
  740.          (push-in tn-next* tn live-list)
  741.          (setf (sbit live-in num) 1)))
  742.  
  743.       (setf (tn-local-conflicts tn) bits))))
  744.  
  745.     (make-debug-environment-tns-live block live-bits live-list)))
  746.  
  747.  
  748. ;;; DO-SAVE-P-STUFF  --  Internal
  749. ;;;
  750. ;;;    A function called in Conflict-Analyze-1-Block when we have a VOP with
  751. ;;; SAVE-P true.  We compute the save-set, and if :FORCE-TO-STACK, force all
  752. ;;; the live TNs to be stack environment TNs.
  753. ;;;
  754. (defun do-save-p-stuff (vop block live-bits)
  755.   (declare (type vop vop) (type ir2-block block)
  756.        (type local-tn-bit-vector live-bits))
  757.   (let ((ss (compute-save-set vop live-bits)))
  758.     (setf (vop-save-set vop) ss)
  759.     (when (eq (vop-info-save-p (vop-info vop)) :force-to-stack)
  760.       (do-live-tns (tn ss block)
  761.     (unless (eq (tn-kind tn) :component)
  762.       (force-tn-to-stack tn)
  763.       (unless (eq (tn-kind tn) :environment)
  764.         (convert-to-environment-tn
  765.          tn
  766.          (block-environment (ir2-block-block block))))))))
  767.   (undefined-value))
  768.  
  769.  
  770. (eval-when (compile eval)
  771.  
  772. ;;; Frob-More-TNs  --  Internal
  773. ;;;
  774. ;;;    Used in SCAN-VOP-REFS to simultaneously do something to all of the TNs
  775. ;;; referenced by a big more arg.  We have to treat these TNs specially, since
  776. ;;; when we set or clear the bit in the live TNs, the represents a change in
  777. ;;; the liveness of all the more TNs.  If we iterated as normal, the next more
  778. ;;; ref would be thought to be not live when it was, etc.  We update Ref to be
  779. ;;; the last :more ref we scanned, so that the main loop will step to the next
  780. ;;; non-more ref.
  781. ;;;
  782. (defmacro frob-more-tns (action)
  783.   `(when (eq (svref ltns num) :more)
  784.      (let ((prev ref))
  785.        (do ((mref (tn-ref-next-ref ref) (tn-ref-next-ref mref)))
  786.        ((null mref))
  787.      (let ((mtn (tn-ref-tn mref)))
  788.        (unless (eql (tn-local-number mtn) num)
  789.          (return))
  790.        ,action)
  791.      (setq prev mref))
  792.        (setq ref prev))))
  793.  
  794.  
  795. ;;; SCAN-VOP-REFS  --  Internal
  796. ;;;
  797. ;;;        Handle the part of CONFLICT-ANALYZE-1-BLOCK that scans the REFs for the
  798. ;;; current VOP.  This macro shamelessly references free variables in C-A-1-B.
  799. ;;;
  800. (defmacro scan-vop-refs ()
  801.   '(do ((ref (vop-refs vop) (tn-ref-next-ref ref)))
  802.        ((null ref))
  803.      (let* ((tn (tn-ref-tn ref))
  804.         (num (tn-local-number tn)))
  805.        (cond
  806.     ((not num))
  807.     ((not (zerop (sbit live-bits num)))
  808.      (when (tn-ref-write-p ref)
  809.        (setf (sbit live-bits num) 0)
  810.        (deletef-in tn-next* live-list tn)
  811.        (frob-more-tns (deletef-in tn-next* live-list mtn))))
  812.     (t
  813.      (assert (not (tn-ref-write-p ref)))
  814.      (note-conflicts live-bits live-list tn num)
  815.      (frob-more-tns (note-conflicts live-bits live-list mtn num))
  816.      (setf (sbit live-bits num) 1)
  817.      (push-in tn-next* tn live-list)
  818.      (frob-more-tns (push-in tn-next* mtn live-list)))))))
  819.  
  820.  
  821. ;;; ENSURE-RESULTS-LIVE  --  Internal
  822. ;;;
  823. ;;;    This macro is called by CONFLICT-ANALYZE-1-BLOCK to scan the current
  824. ;;; VOP's results, and make any dead ones live.  This is necessary, since even
  825. ;;; though a result is dead after the VOP, it may be in use for an extended
  826. ;;; period within the VOP (especially if it has :FROM specified.)  During this
  827. ;;; interval, temporaries must be noted to conflict with the result.  More
  828. ;;; results are finessed in COMPUTE-INITIAL-CONFLICTS, so we ignore them here.
  829. ;;;
  830. (defmacro ensure-results-live ()
  831.   '(do ((res (vop-results vop) (tn-ref-across res)))
  832.        ((null res))
  833.      (let* ((tn (tn-ref-tn res))
  834.         (num (tn-local-number tn)))
  835.        (when (and num (zerop (sbit live-bits num)))
  836.      (unless (eq (svref ltns num) :more)
  837.        (note-conflicts live-bits live-list tn num)
  838.        (setf (sbit live-bits num) 1)
  839.        (push-in tn-next* tn live-list))))))
  840.  
  841. ); Eval-When (Compile Eval)
  842.  
  843.  
  844. ;;; Conflict-Analyze-1-Block  --  Internal
  845. ;;;
  846. ;;;    Compute the block-local conflict information for Block.  We iterate over
  847. ;;; all the TN-Refs in a block in reference order, maintaining the set of live
  848. ;;; TNs in both a list and a bit-vector representation.
  849. ;;;
  850. (defun conflict-analyze-1-block (block)
  851.   (declare (type ir2-block block))
  852.   (multiple-value-bind
  853.       (live-bits live-list)
  854.       (compute-initial-conflicts block)
  855.     (let ((ltns (ir2-block-local-tns block)))
  856.       (do ((vop (ir2-block-last-vop block)
  857.         (vop-prev vop)))
  858.       ((null vop))
  859.     (when (vop-info-save-p (vop-info vop))
  860.       (do-save-p-stuff vop block live-bits))
  861.     (ensure-results-live)
  862.     (scan-vop-refs)))))
  863.  
  864.  
  865. ;;; Lifetime-Post-Pass  --  Internal
  866. ;;;
  867. ;;;    Conflict analyze each block, and also add it 
  868. (defun lifetime-post-pass (component)
  869.   (declare (type component component))
  870.   (do-ir2-blocks (block component)
  871.     (conflict-analyze-1-block block)))
  872.  
  873.  
  874. ;;;; Alias TN stuff:
  875.  
  876. ;;; MERGE-ALIAS-BLOCK-CONFLICTS  --  Internal
  877. ;;;
  878. ;;;    Destructively modify Oconf to include the conflict information in Conf.
  879. ;;; 
  880. (defun merge-alias-block-conflicts (conf oconf)
  881.   (declare (type global-conflicts conf oconf))
  882.   (let* ((kind (global-conflicts-kind conf))
  883.      (num (global-conflicts-number conf))
  884.      (okind (global-conflicts-kind oconf))
  885.      (onum (global-conflicts-number oconf))
  886.      (block (global-conflicts-block oconf))
  887.      (ltns (ir2-block-local-tns block)))
  888.     (cond
  889.      ((eq okind :live))
  890.      ((eq kind :live)
  891.       (setf (global-conflicts-kind oconf) :live)
  892.       (setf (svref ltns onum) nil)
  893.       (setf (global-conflicts-number oconf) nil))
  894.      (t
  895.       (unless (eq kind okind)
  896.     (setf (global-conflicts-kind oconf) :read))
  897.       ;;
  898.       ;; Make original conflict with all the local TNs the alias conflicted
  899.       ;; with.
  900.       (bit-ior (global-conflicts-conflicts oconf)
  901.            (global-conflicts-conflicts conf)
  902.            t)
  903.       (flet ((frob (x)
  904.            (unless (zerop (sbit x num))
  905.          (setf (sbit x onum) 1))))
  906.     ;;
  907.     ;; Make all the local TNs that conflicted with the alias conflict
  908.     ;; with the original.
  909.     (dotimes (i (ir2-block-local-tn-count block))
  910.       (let ((tn (svref ltns i)))
  911.         (when (and tn (not (eq tn :more))
  912.                (null (tn-global-conflicts tn)))
  913.           (frob (tn-local-conflicts tn)))))
  914.     ;;
  915.     ;; Same for global TNs...
  916.     (do ((current (ir2-block-global-tns block)
  917.               (global-conflicts-next current)))
  918.         ((null current))
  919.       (unless (eq (global-conflicts-kind current) :live)
  920.         (frob (global-conflicts-conflicts current))))
  921.     ;;
  922.     ;; Make the original TN live everywhere that the alias was live.
  923.     (frob (ir2-block-written block))
  924.     (frob (ir2-block-live-in block))
  925.     (frob (ir2-block-live-out block))
  926.     (do ((vop (ir2-block-start-vop block)
  927.           (vop-next vop)))
  928.         ((null vop))
  929.       (let ((sset (vop-save-set vop)))
  930.         (when sset (frob sset)))))))
  931.     ;;
  932.     ;; Delete the alias's conflict info.
  933.     (when num
  934.       (setf (svref ltns num) nil))
  935.     (deletef-in global-conflicts-next (ir2-block-global-tns block) conf))
  936.  
  937.   (undefined-value))
  938.  
  939.  
  940. ;;; CHANGE-GLOBAL-CONFLICTS-TN  --  Internal
  941. ;;;
  942. ;;;    Co-opt Conf to be a conflict for TN.
  943. ;;;
  944. (defun change-global-conflicts-tn (conf new)
  945.   (declare (type global-conflicts conf) (type tn new))
  946.   (setf (global-conflicts-tn conf) new)
  947.   (let ((ltn-num (global-conflicts-number conf))
  948.     (block (global-conflicts-block conf)))
  949.     (deletef-in global-conflicts-next (ir2-block-global-tns block) conf)
  950.     (setf (global-conflicts-next conf) nil)
  951.     (insert-block-global-conflict conf block)
  952.     (when ltn-num
  953.       (setf (svref (ir2-block-local-tns block) ltn-num) new)))
  954.   (undefined-value))
  955.  
  956.  
  957. ;;; ENSURE-GLOBAL-TN  --  Internal
  958. ;;;
  959. ;;;    Do CONVERT-TO-GLOBAL on TN if it has no global conflicts.  Copy the
  960. ;;; local conflicts into the global bit vector.
  961. ;;;
  962. (defun ensure-global-tn (tn)
  963.   (declare (type tn tn))
  964.   (cond ((tn-global-conflicts tn))
  965.     ((tn-local tn)
  966.      (convert-to-global tn)
  967.      (bit-ior (global-conflicts-conflicts (tn-global-conflicts tn))
  968.           (tn-local-conflicts tn)
  969.           t))
  970.     (t
  971.      (assert (and (null (tn-reads tn)) (null (tn-writes tn))))))
  972.   (undefined-value))
  973.  
  974.   
  975. ;;; MERGE-ALIAS-CONFLICTS  --  Internal
  976. ;;;
  977. ;;;    For each :ALIAS TN, destructively merge the conflict info into the
  978. ;;; original TN and replace the uses of the alias.
  979. ;;;
  980. ;;; For any block that uses only the alias TN, just insert that conflict into
  981. ;;; the conflicts for the original TN, changing the LTN map to refer to the
  982. ;;; original TN.  This gives a result indistinguishable from the what there
  983. ;;; would have been if the original TN had always been referenced.  This leaves
  984. ;;; no sign that an alias TN was ever involved.
  985. ;;;
  986. ;;; If a block has references to both the alias and the original TN, then we
  987. ;;; call MERGE-ALIAS-BLOCK-CONFLICTS to combine the conflicts into the original
  988. ;;; conflict.
  989. ;;; 
  990. (defun merge-alias-conflicts (component)
  991.   (declare (type component component))
  992.   (do ((tn (ir2-component-alias-tns (component-info component))
  993.        (tn-next tn)))
  994.       ((null tn))
  995.     (let ((original (tn-save-tn tn)))
  996.       (ensure-global-tn tn)
  997.       (ensure-global-tn original)
  998.       (let ((conf (tn-global-conflicts tn))
  999.         (oconf (tn-global-conflicts original))
  1000.         (oprev nil))
  1001.     (loop
  1002.       (unless oconf
  1003.         (if oprev
  1004.         (setf (global-conflicts-tn-next oprev) conf)
  1005.         (setf (tn-global-conflicts original) conf))
  1006.         (do ((current conf (global-conflicts-tn-next current)))
  1007.         ((null current))
  1008.           (change-global-conflicts-tn current original))
  1009.         (return))
  1010.       (let* ((block (global-conflicts-block conf))
  1011.          (num (ir2-block-number block))
  1012.          (onum (ir2-block-number (global-conflicts-block oconf))))
  1013.  
  1014.         (cond ((< onum num)
  1015.            (shiftf oprev oconf (global-conflicts-tn-next oconf)))
  1016.           ((> onum num)
  1017.            (if oprev
  1018.                (setf (global-conflicts-tn-next oprev) conf)
  1019.                (setf (tn-global-conflicts original) conf))
  1020.            (change-global-conflicts-tn conf original)
  1021.            (shiftf oprev conf (global-conflicts-tn-next conf) oconf))
  1022.           (t
  1023.            (merge-alias-block-conflicts conf oconf)
  1024.            (shiftf oprev oconf (global-conflicts-tn-next oconf))
  1025.            (setf conf (global-conflicts-tn-next conf)))))
  1026.       (unless conf (return))))
  1027.  
  1028.       (flet ((frob (refs)
  1029.            (let ((ref refs)
  1030.              (next nil))
  1031.          (loop
  1032.            (unless ref (return))
  1033.            (setq next (tn-ref-next ref))
  1034.            (change-tn-ref-tn ref original)
  1035.            (setq ref next)))))
  1036.     (frob (tn-reads tn))
  1037.     (frob (tn-writes tn)))
  1038.       (setf (tn-global-conflicts tn) nil)))
  1039.  
  1040.   (undefined-value))
  1041.  
  1042.  
  1043. ;;; Lifetime-Analyze  --  Interface
  1044. ;;;
  1045. ;;;
  1046. (defun lifetime-analyze (component)
  1047.   (lifetime-pre-pass component)
  1048.   (setup-environment-live-conflicts component)
  1049.   (lifetime-flow-analysis component)
  1050.   (lifetime-post-pass component)
  1051.   (merge-alias-conflicts component))
  1052.  
  1053.  
  1054. ;;;; Conflict testing:
  1055.  
  1056. ;;; TNs-Conflict-Local-Global  --  Internal
  1057. ;;;
  1058. ;;;    Test for a conflict between the local TN X and the global TN Y.  We just
  1059. ;;; look for a global conflict of Y in X's block, and then test for conflict in
  1060. ;;; that block.
  1061. ;;; [### Might be more efficient to scan Y's global conflicts.  This depends on
  1062. ;;; whether there are more global TNs than blocks.]
  1063. ;;;
  1064. (defun tns-conflict-local-global (x y)
  1065.   (let ((block (tn-local x)))
  1066.     (do ((conf (ir2-block-global-tns block)
  1067.            (global-conflicts-next conf)))
  1068.     ((null conf) nil)
  1069.       (when (eq (global-conflicts-tn conf) y)
  1070.     (let ((num (global-conflicts-number conf)))
  1071.       (return (or (not num)
  1072.               (not (zerop (sbit (tn-local-conflicts x)
  1073.                     num))))))))))
  1074.  
  1075.  
  1076. ;;; TNs-Conflict-Global-Global  --  Internal
  1077. ;;;
  1078. ;;;    Test for conflict between two global TNs X and Y.
  1079. ;;;
  1080. (defun tns-conflict-global-global (x y)
  1081.   (declare (type tn x y))
  1082.   (let* ((x-conf (tn-global-conflicts x))
  1083.      (x-num (ir2-block-number (global-conflicts-block x-conf)))
  1084.      (y-conf (tn-global-conflicts y))
  1085.      (y-num (ir2-block-number (global-conflicts-block y-conf))))
  1086.  
  1087.     (macrolet ((advance (n c)
  1088.          `(progn
  1089.             (setq ,c (global-conflicts-tn-next ,c))
  1090.             (unless ,c (return-from tns-conflict-global-global nil))
  1091.             (setq ,n (ir2-block-number (global-conflicts-block ,c)))))
  1092.            (scan (g l lc)
  1093.          `(do ()
  1094.               ((>= ,g ,l))
  1095.             (advance ,l ,lc))))
  1096.  
  1097.       (loop
  1098.     ;; x-conf, y-conf true, x-num, y-num corresponding block numbers.
  1099.     (scan x-num y-num y-conf)
  1100.     (scan y-num x-num x-conf)
  1101.     (when (= x-num y-num)
  1102.       (let ((ltn-num-x (global-conflicts-number x-conf)))
  1103.         (unless (and ltn-num-x
  1104.              (global-conflicts-number y-conf)
  1105.              (zerop (sbit (global-conflicts-conflicts y-conf)
  1106.                       ltn-num-x)))
  1107.           (return t))
  1108.         (advance x-num x-conf)
  1109.         (advance y-num y-conf)))))))
  1110.  
  1111.  
  1112. ;;; TNs-Conflict  --  Interface
  1113. ;;;
  1114. ;;;    Return true if X and Y are distinct and the lifetimes of X and Y overlap
  1115. ;;; at any point.
  1116. ;;;
  1117. (defun tns-conflict (x y)
  1118.   (declare (type tn x y))
  1119.   (let ((x-kind (tn-kind x))
  1120.     (y-kind (tn-kind y)))
  1121.     (cond ((eq x y) nil)
  1122.       ((or (eq x-kind :component) (eq y-kind :component)) t)
  1123.       ((tn-global-conflicts x)
  1124.        (if (tn-global-conflicts y)
  1125.            (tns-conflict-global-global x y)
  1126.            (tns-conflict-local-global y x)))
  1127.       ((tn-global-conflicts y)
  1128.        (tns-conflict-local-global x y))
  1129.       (t
  1130.        (and (eq (tn-local x) (tn-local y))
  1131.         (not (zerop (sbit (tn-local-conflicts x)
  1132.                   (tn-local-number y)))))))))
  1133.